﻿using System;
using System.Collections.Generic;

using Sgs.Core;
using static Sgs.Utils.Method;


namespace Sgs.Model
{
    class Player
    {
        public int Index;
        private int ControllerIndex;
        public PlayerIdentity Identity;
        public Hero Hero = null;
        public List<Card> Cards = null;
        private readonly Store Store;
        private readonly Controller Controller;

        private bool CanGetCards = true;
        private bool CanPushCards = true;
        private Card OnUsingCard = null; // 指向即将使用的牌
        private int AvailTouch = 1; //攻击范围
        private int AvailUse杀 = 1;

        public enum PlayerIdentity
        {
            主公, 忠臣, 反贼, 内奸
        }

        public Player(int Index, PlayerIdentity Identity, Hero Hero, List<Card> Cards, Controller Controller)
        {
            this.Index = Index;
            this.Identity = Identity;
            this.Cards = Cards;
            this.Hero = Hero;
            Store = Controller.PlayAccessStore;
            this.Controller = Controller;
        }

        public int GetControllerIndex()
        {
            return ControllerIndex;
        }


        public void SetControllerIndex(int ControllerIndex)
        {
            this.ControllerIndex = ControllerIndex;
        }

        public override string ToString()
        {
            return $"{ Index + 1}号位 身份={Identity} 手牌数量={Cards.Count}";
        }

        public void UnSafeShowDetails()
        {
            Console.WriteLine(this);
            Console.WriteLine(Hero);
            ListCards();
            Console.WriteLine(Store);
            Console.WriteLine();
        }

        /// <summary>
        /// 玩家展示手牌
        /// </summary>
        public void ListCards()
        {
            foreach (Card item in Cards)
            {
                Console.WriteLine($"{Cards.IndexOf(item) + 1}：" + item);
            }
        }

        /// <summary>
        /// 开始回合
        /// </summary>
        public void StartRound()
        {
            Console.WriteLine($"{ Index + 1}号位开始回合：\n 当前手牌：");
            ListCards(); //展示手牌
            if (CanGetCards) //可以摸牌
            {
                /*Console.Write("你选择摸多少张牌？");
                GetCards(SafeReadNumber()); //开始摸牌
               */
                GetCards(2); //默认摸2张牌

            }
            else
            {
                CanGetCards = true;
            }

            if (CanPushCards) //可以出牌
            {
                Console.WriteLine("\n出牌阶段开始");
                AvailUse杀 = 999;
                PushCards(); //开始出牌
            }
            else
            {
                CanPushCards = true;
            }

            ThrowCards(); // 弃牌阶段

            Console.WriteLine("\n*************************************\n");
            NextPlayer(); //下一位玩家回合开始
        }

        /// <summary>
        /// 玩家获得牌
        /// </summary>
        /// <param name="Cards">获得牌的List</param>
        public void AddCards(List<Card> Cards)
        {
            foreach (Card item in Cards)
            {
                this.Cards.Add(item);
            }
        }

        /// <summary>
        ///  从牌堆里摸牌
        /// </summary>
        /// <param name="CardNumber"></param>
        public void GetCards(int CardNumber)
        {
            if (CardNumber <= 0)
            {
                Console.WriteLine("输入的数据不合法，请重新输入");
                Console.Write("你选择摸多少张牌？");
                GetCards(SafeReadNumber());
            }
            Console.WriteLine("\n" + $"{ Index + 1}号位从牌堆里摸了{CardNumber}张牌" + "\n");

            List<Card> cards = Store.DispatchCards(CardNumber);
            if (cards.Count > 0 && cards[0].Name == "平局令牌")
            {
                Controller.GameOver(Controller.GameOverOptions.平局);
            }
            else
            {
                AddCards(cards);
                Console.WriteLine($"{Index + 1}号位当前手牌：");
                ListCards();
                Console.WriteLine("\n" + Store);

            }
        }

        /// <summary>
        /// 开始出牌
        /// </summary>
        public void PushCards()
        {
            if (OnUsingCard != null)
            {
                OnUsingCard = null;
            }
            Console.WriteLine($"\n{Index + 1}号位正在出牌，当前手牌：\n");
            ListCards();
            Console.Write("\n请输入需要使用的牌的编号，输入0则结束出牌阶段：");
            int CardIndex = SafeReadNumber();
            if (CardIndex < 0 || CardIndex > Cards.Count)
            {
                Console.WriteLine("\n输入的数据不合法，请重新输入");
                PushCards();
            }
            else if (CardIndex > 0)
            {
                OnUsingCard = Cards[CardIndex - 1]; //修改指向
                Cards[CardIndex - 1].Effect(this);
                PushCards();
            }
            else
            {
                Console.WriteLine("\n出牌阶段结束");
            }
        }

        /// <summary>
        /// 弃置手牌，进入弃牌堆
        /// </summary>
        public void ThrowCards()
        {
            Console.WriteLine("\n进入弃牌阶段，当前手牌：");
            ListCards();
            if (Cards.Count <= Hero.PlayerAccessHP)
            {
                Console.WriteLine("不需要弃牌，弃牌阶段结束");
                Console.WriteLine(Store);
            }
            else
            {
                Console.WriteLine($"\n需要弃置{Cards.Count - Hero.PlayerAccessHP}张牌");
                Console.WriteLine("请输入要弃置的编号：");
                for (int i = 0; i < Cards.Count - Hero.PlayerAccessHP; i++)
                {
                    int CardIndex = SafeReadNumber();
                    if (0 < CardIndex && CardIndex <= Cards.Count)
                    {
                        Store.ThrowOneCard(Cards[CardIndex - 1]);
                        Cards.RemoveAt(CardIndex - 1);
                        ThrowCards();
                    }
                    else
                    {
                        Console.WriteLine("\n 输入的数据不合法，请重新输入");
                        ThrowCards();
                    }

                }
            }
        }

        public string Wait(string Message = "等待玩家操作 …")
        {
            Console.WriteLine();
            Console.Write(Message);
            return Console.ReadLine();
        }

        /// <summary>
        /// 获取与指定玩家的距离
        /// </summary>
        /// <param name="TargetPlayerIndex">指定玩家的Index</param>
        /// <returns></returns>
        public int GetDistance(int TargetPlayerIndex)
        {
            int distance = Math.Abs(ControllerIndex - Controller.GetPlayerByIndex(TargetPlayerIndex).ControllerIndex);
            if (distance > Math.Floor(Controller.PlayerCount * 0.5) + 1)
            {
                distance = Controller.PlayerCount - distance;
            }
            return distance;
        }

        /// <summary>
        /// 下一位玩家回合开始
        /// </summary>  
        public void NextPlayer()
        {
            int NextPlayerIndex = (ControllerIndex + 1) % Controller.PlayerCount;
            Controller.LoadPlayer(NextPlayerIndex);
        }

        public Player GetNextPlayer()
        {
            int NextPlayerIndex = (ControllerIndex + 1) % Controller.PlayerCount;
            return Controller.UnSafeTouchAnotherPlayer(NextPlayerIndex);
        }

        public Player GetBackPlayer()
        {
            int NextPlayerIndex = (ControllerIndex + Controller.PlayerCount - 1) % Controller.PlayerCount;
            return Controller.UnSafeTouchAnotherPlayer(NextPlayerIndex);
        }

        public void ThrowAllCards()
        {
            for (int i = 0; i< Cards.Count; i++)
            {
                Store.ThrowOneCard(Cards[i]);
            }
            Cards.Clear();
        }

        public void Use桃()
        {
            if (Hero.PlayerAccessHP >= Hero.HP)
            {
                Console.WriteLine("没有损失体力，无法使用桃");
            }
            else
            {
                Hero.PlayerAccessHP++;
                Store.ThrowOneCard(OnUsingCard);
                Cards.Remove(OnUsingCard);
            }
            OnUsingCard = null;
        }

        public void Use闪()
        {
            Console.WriteLine("无法直接使用闪");
        }

        public void TakeOver()
        {
            Console.WriteLine($"{Index + 1}号位响应结束");
            Console.WriteLine("此时牌堆：" + Store);
            Console.WriteLine("******************************\n");
        }

        public void Take杀(int FromTarget)
        {
            Console.WriteLine($"\n{Index + 1}号位参与了事件,{Index + 1}号位成为了{FromTarget + 1}号位的杀的指向目标，现在进入{Index + 1}号位视角\n当前手牌：");
            ListCards();

            Console.Write($"成为杀的目标，请在手牌中选择一张\"闪\"来响应，输入0则放弃使用：");
            int CardIndex = SafeReadNumber();
            while (CardIndex < 0 || CardIndex > Cards.Count || (CardIndex > 0 && Cards[CardIndex - 1].Name != "闪"))
            {
                Console.WriteLine("目标不合法，请重新输入：");
                CardIndex = SafeReadNumber();
            }

            if (CardIndex != 0)
            {
                Console.WriteLine("\n" + $"{Index + 1}号位使用了一张\"闪\"");
                Console.WriteLine("此牌明细：" + Cards[CardIndex - 1]);
                Store.ThrowOneCard(Cards[CardIndex - 1]);
                Cards.RemoveAt(CardIndex - 1);
            }
            else
            {
                TakeHurt(1, FromTarget);
            }

            TakeOver();
        }


        /// <summary>
        /// 受到伤害
        /// </summary>
        /// <param name="HurtNumber">伤害数量</param>
        /// <param name="FromTarget">目标来源标号</param>
        public void TakeHurt(int HurtNumber, int FromTarget)
        {
            Hero.PlayerAccessHP = Hero.PlayerAccessHP - HurtNumber;
            Console.WriteLine($"\n{Index + 1}号位受到了{FromTarget + 1}号位杀造成的一点伤害");
            Console.WriteLine($"{Index + 1}号位体力减1，此时体力值为{Hero.PlayerAccessHP}，体力上限为{Hero.HP}\n");
            if (Hero.PlayerAccessHP <= 0)
            {
                //濒死检查
                SavePlayer(Index, FromTarget);
            }
        }

        /// <summary>
        /// 救援濒死玩家
        /// </summary>
        /// <param name="DyingPlayerIndex"></param>
        /// <param name="桃Number"></param>
        public void SavePlayer(int DyingPlayerIndex, int FromTarget)
        {
            if (Controller.GetPlayerByIndex(DyingPlayerIndex).Hero.PlayerAccessHP > 0)
            {
                Console.WriteLine($"{DyingPlayerIndex + 1}号位脱离了濒死状态，体力值为1");
                return;
            }
            int NumberOfPeach = 1 - Controller.GetPlayerByIndex(DyingPlayerIndex).Hero.PlayerAccessHP;
            Console.WriteLine($"{DyingPlayerIndex + 1}号位处于濒死状态，现在向{Index + 1}号位求桃，需要{NumberOfPeach}个桃");
            Console.WriteLine($"{Index + 1}号位手牌列表：");

            ListCards();

            Console.Write($"目前还需要{NumberOfPeach}个桃，请选择是否使用桃，输入0则放弃");

            int CardIndex = SafeReadNumber();
            while (CardIndex < 0 || CardIndex > Cards.Count || (CardIndex > 0 && Cards[CardIndex - 1].Name != "桃"))
            {
                Console.WriteLine("目标不合法，请重新输入：");
                CardIndex = SafeReadNumber();
            }

            if (CardIndex != 0)
            {
                Controller.GetPlayerByIndex(DyingPlayerIndex).Hero.PlayerAccessHP++;
                Console.WriteLine($"{Index + 1}号位使用了一张桃，{DyingPlayerIndex + 1}号位恢复了1点体力");
                Console.WriteLine("桃的明细：" + Cards[CardIndex - 1] + "\n此时牌堆" + Store);
                Store.ThrowOneCard(Cards[CardIndex - 1]);
                Cards.RemoveAt(CardIndex - 1);
                SavePlayer(DyingPlayerIndex, FromTarget);
            }
            else
            {
                Console.WriteLine($"{Index + 1}号位放弃对{DyingPlayerIndex + 1}号位使用桃\n");
                if (Controller.GetPlayerByIndex(DyingPlayerIndex).GetBackPlayer().Index != Index)
                {
                    GetNextPlayer().SavePlayer(DyingPlayerIndex, FromTarget);
                }
                else
                {
                    Controller.GetPlayerByIndex(DyingPlayerIndex).ThrowAllCards();
                    Console.WriteLine($"{DyingPlayerIndex + 1}号位死亡，并弃置了所有牌，此时牌堆：\n" + Store + "\n");

                    if (Controller.GetPlayerByIndex(DyingPlayerIndex).Identity == PlayerIdentity.反贼)
                    {
                        Controller.GetPlayerByIndex(FromTarget).GetCards(3);
                        Console.WriteLine($"\n{DyingPlayerIndex + 1}号位身份为反贼，{FromTarget + 1}号位从牌堆获得三张牌\n");
                        Console.WriteLine(Store + "\n");
                    }
                    else if (Controller.GetPlayerByIndex(DyingPlayerIndex).Identity == PlayerIdentity.忠臣 
                        && Controller.GetPlayerByIndex(FromTarget).Identity == PlayerIdentity.主公)
                    {
                        Console.WriteLine($"{DyingPlayerIndex + 1}号位身份为忠臣，{FromTarget + 1}号位主公需要弃置所有牌");
                        ThrowAllCards();
                        Console.WriteLine(Store + "\n");
                    }

                    //移除角色
                    Controller.RemovePlayer(DyingPlayerIndex);
                }
            }
        }

        public void Use杀()
        {
            if (AvailUse杀 > 0)
            {
                AvailUse杀--;
            }
            else
            {
                Console.Write("该回合出杀次数已用完");
                return;
            }
            Console.WriteLine("选择使用了杀\n详细信息：" + OnUsingCard);
            Console.Write($"您现在是{Index + 1}号位，请输入杀的指向目标，输入0则放弃使用杀：");
            int TargetIndex = SafeReadNumber();
            if (TargetIndex < 0 || TargetIndex == Index + 1)
            {
                Console.WriteLine("\n输入的数据不合法或者您指向了自己，请重新输入");
                Use杀();
            }
            else if (TargetIndex == 0)
            {
                OnUsingCard = null;
                return;
            }

            else if(Controller.GetPlayerByIndex(TargetIndex - 1) == null)
            {
                Console.WriteLine("\n目标角色不存在，请重新输入");
                Use杀();
            }
            else if (AvailTouch < GetDistance(TargetIndex-1))
            {
                Console.WriteLine("\n目标角色不在您的攻击范围内，请重新输入");
                Use杀();
            }
            else
            {
                Store.ThrowOneCard(OnUsingCard);
                Cards.Remove(OnUsingCard);
                OnUsingCard = null;
                Console.WriteLine($"{Index + 1}号位的\"杀\"进入弃牌堆");
                Console.WriteLine("此时牌堆：" + Store);
                Controller.GetPlayerByIndex(TargetIndex - 1).Take杀(Index);
            }
        }
    }
}
